package com.boil.qz.safekavass.shiro.filter;

import com.boil.pojo.ResultVo;
import com.boil.util.Constants;
import com.boil.util.FastJsonUtils;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.AccessControlFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;


/**
 * Created by ChenYong on 2017-05-03.
 * <br>
 * Session 失效的过滤器。
 */
public class SessionTimeoutFilter extends AccessControlFilter {
    /**
     * 日志
     */
    private static Logger log = LoggerFactory.getLogger(SessionTimeoutFilter.class);

    /**
     * 是否允许访问。
     */
    @Override
    protected boolean isAccessAllowed(ServletRequest request, // 请求
                                      ServletResponse response, // 响应
                                      Object mappedValue) throws Exception {
        // 获取登录用户
        Subject subject = getSubject(request, response);

        return subject.isAuthenticated();
    }

    /**
     * 被拒绝访问时执行，即 isAccessAllowed() 返回 false 时执行。
     * <br>
     * 此方法用于处理 Session 失效。
     */
    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
        // 获取请求
        HttpServletRequest request1 = (HttpServletRequest) request;
        // 获取响应
        HttpServletResponse response1 = (HttpServletResponse) response;
        // 获取登录用户的操作信息
        Subject subject = getSubject(request, response);
        // 获取 Session
        Session session = subject.getSession();

        // 在 Session 中存入 Session 失效的标记
        session.setAttribute(Constants.SESSION_TIMEOUT, Constants.LOGIN_TIMEOUT);

        // Ajax 请求
        if (Constants.AJAX_REQUEST.equalsIgnoreCase(request1.getHeader(Constants.REQUEST_TYPE))) {
            log.error("Ajax 请求--->用户未登录或登录超时，已被拦截！");

            response1.setStatus(HttpServletResponse.SC_UNAUTHORIZED);

            // 结果
            ResultVo resultVo = new ResultVo();
            resultVo.setResultCode(Constants.LOGIN_TIMEOUT);
            resultVo.setResultMsg(Constants.LOGIN_TIMEOUT_MSG);

            PrintWriter pw = null;

            try {
                response1.getWriter().write(FastJsonUtils.bean2Json(resultVo));
            } catch (Exception e) {
                log.error("Ajax 请求--->响应用户未登录或登录超时时出现异常，异常信息如下：{}", e);
            } finally {
                try {
                    if (pw != null) {
                        pw.close();
                    }
                } catch (Exception e) {
                    log.error("Ajax 请求--->响应用户未登录或登录超时，关闭响应流时出现异常，异常信息如下：{}", e);
                }
            }

            // 非 Ajax 请求
        } else {
            // 请求来自 Uploadifive 文件上传
            if (Constants.UPLOADIFIVE.equals(request1.getParameter(Constants.UPLOADIFIVE))) {
                log.error("Uploadifive 文件上传请求--->用户未登录或登录超时，已被拦截！");

                // response1.setStatus(HttpServletResponse.SC_UNAUTHORIZED);

                // 结果
                ResultVo resultVo = new ResultVo();
                resultVo.setResultCode(Constants.LOGIN_TIMEOUT);
                resultVo.setResultMsg(Constants.LOGIN_TIMEOUT_MSG);

                PrintWriter pw = null;

                try {
                    response1.getWriter().write(FastJsonUtils.bean2Json(resultVo));
                } catch (Exception e) {
                    log.error("Uploadifive 文件上传请求--->响应用户未登录或登录超时时出现异常，异常信息如下：{}", e);
                } finally {
                    try {
                        if (pw != null) {
                            pw.close();
                        }
                    } catch (Exception e) {
                        log.error("Uploadifive 文件上传请求--->响应用户未登录或登录超时，关闭响应流时出现异常，异常信息如下：{}", e);
                    }
                }

                // 普通请求
            } else {
                log.error("非 Ajax 请求--->用户未登录或登录超时，已被拦截，跳转至登录页面！");

                saveRequestAndRedirectToLogin(request, response);
            }

        }

        return false;
    }
}